﻿using System;
using Dogshow.BusinessLogic.Managers;
using Dogshow.Infrastructure.Exceptions;
using Dogshow.Model;
using DogshowRepository;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Dogshow.BusinessLogicTests.Managers
{
    [TestClass]
    public class PasManagerFixtures
    {
        private PasManager m_Manager;

        private Mock<IPsiRepository> m_PsiRepository;

        private Mock<IKorisniciRepository> m_KorisniciRepository;

        [TestInitialize]
        public void TestInit()
        {
            m_KorisniciRepository = new Mock<IKorisniciRepository>();
            m_PsiRepository = new Mock<IPsiRepository>();
            m_Manager = new PasManager(m_PsiRepository.Object, m_KorisniciRepository.Object);
        }

        [TestMethod]
        public void Sacuvaj_Omiljenog_Psa()
        {
            // Arrange
            var pas = new Pas();
            const string korisnickoIme = "zeks";
            var korisnik = new Korisnik {KorisnickoIme = korisnickoIme, IdKinologa = 5};
            m_KorisniciRepository.Setup(x => x.VratiPoKorisnickomImenu(korisnickoIme)).Returns(korisnik);

            // Act
            m_Manager.SacuvajOmiljenogPsa(pas, korisnickoIme);

            // Assert
            m_PsiRepository.Verify(x => x.SacuvajPsaUOmiljene(pas, korisnickoIme));
        }

        [TestMethod][ExpectedException(typeof(ValidationException))]
        public void Sacuvaj_Psa_Sa_Rodovnikom_Koji_Vec_Postoji()
        {
            // Arrange
            var pas = new Pas {BrojRodovnika = "JR/5541", Id = 3};
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas(){Id = 1, IdVlasnika = 1});

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        public void Sacuvaj_Psa_Sa_Rodovnikom_Koji_Je_Njegov()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3 };
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas(){Id = 3, IdVlasnika = 1});

            // Act
            m_Manager.SacuvajPsa(pas);

            // Assert
            m_PsiRepository.Verify(x => x.Sacuvaj(pas));
        }

        [TestMethod]
        [ExpectedException(typeof(PasBezVlasnikaException))]
        public void Sacuvaj_Psa_Kada_Isti_Rodovnik_Postoji_Ali_Nema_Vlasnika()
        {
            // Arrange
            var pas = new Pas {BrojRodovnika = "JR/6661"};
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns((new Pas()));

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Rasa_Oca_Se_Ne_Poklapa()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdOca = 1, IdRase = 5};
            var otac = new Pas {Id = 1, IdRase = 3};
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdOca.Value)).Returns(otac);

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Rasa_Majke_Se_Ne_Poklapa()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdMajke = 1, IdRase = 5 };
            var majka = new Pas { Id = 1, IdRase = 3 };
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdMajke.Value)).Returns(majka);

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Pas_Je_Stariji_Od_Oca()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdOca = 1, Ostenjen = DateTime.Now};
            var otac = new Pas { Id = 1, Ostenjen = pas.Ostenjen.Value.Subtract(TimeSpan.FromDays(1))};
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdOca.Value)).Returns(otac);

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Pas_Je_Stariji_Od_Majke()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdMajke = 1, Ostenjen = DateTime.Now };
            var majka = new Pas { Id = 1, Ostenjen = pas.Ostenjen.Value.Subtract(TimeSpan.FromDays(1)) };
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdMajke.Value)).Returns(majka);

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Otac_Je_Zenka()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdOca = 1};
            var otac = new Pas { Id = 1, Pol = 2};
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdOca.Value)).Returns(otac);

            // Act
            m_Manager.SacuvajPsa(pas);
        }

        [TestMethod]
        [ExpectedException(typeof(ValidationException))]
        public void Majka_Je_Muzjak()
        {
            // Arrange
            var pas = new Pas { BrojRodovnika = "JR/5541", Id = 3, IdMajke = 1 };
            var majka = new Pas { Id = 1, Pol = 1 };
            m_PsiRepository.Setup(x => x.VratiPsaPoBrojuRodovnika(pas.BrojRodovnika)).Returns(new Pas() { Id = 3, IdVlasnika = 1 });
            m_PsiRepository.Setup(x => x.VratiPoId(pas.IdMajke.Value)).Returns(majka);

            // Act
            m_Manager.SacuvajPsa(pas);
        }
    }
}